﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MultiDAQ_Analysis.Util
{
    public static class Crc32VerilogEquivalent
    {
        private static uint crc = 0xFFFFFFFF;

        public static void Reset()
        {
            crc = 0xFFFFFFFF;
        }

        public static void Init()
        {
            crc = 0xFFFFFFFF;
        }

        public static void Update(byte dataByte)
        {
            bool[] d = new bool[8];
            bool[] c = new bool[32];
            for (int i = 0; i < 32; i++) c[i] = (crc & (1u << i)) != 0;
            for (int i = 0; i < 8; i++) d[i] = (dataByte & (1u << i)) != 0;

            bool[] new_crc = new bool[32];

            new_crc[0] = c[24] ^ c[30] ^ d[1] ^ d[7];
            new_crc[1] = c[25] ^ c[31] ^ d[0] ^ d[6] ^ new_crc[0];
            new_crc[2] = c[26] ^ d[5] ^ new_crc[1];
            new_crc[3] = c[27] ^ d[4] ^ new_crc[2];
            new_crc[4] = c[28] ^ d[3] ^ new_crc[3];
            new_crc[5] = c[29] ^ d[2] ^ new_crc[4];
            new_crc[6] = c[30] ^ d[1] ^ new_crc[5];
            new_crc[7] = c[31] ^ d[0] ^ new_crc[6];
            new_crc[8] = c[0] ^ c[28] ^ d[3] ^ c[27] ^ d[4] ^ c[25] ^ d[6] ^ c[24] ^ d[7];
            new_crc[9] = c[1] ^ c[29] ^ d[2] ^ c[28] ^ d[3] ^ c[26] ^ d[5] ^ c[25] ^ d[6];
            new_crc[10] = c[2] ^ c[29] ^ d[2] ^ c[27] ^ d[4] ^ c[26] ^ d[5] ^ c[24] ^ d[7];
            new_crc[11] = c[3] ^ c[28] ^ d[3] ^ c[27] ^ d[4] ^ c[25] ^ d[6] ^ c[24] ^ d[7];
            new_crc[12] = c[4] ^ c[29] ^ d[2] ^ c[28] ^ d[3] ^ c[26] ^ d[5] ^ c[25] ^ d[6] ^ c[24] ^ c[30] ^ d[1] ^ d[7];
            new_crc[13] = c[5] ^ c[30] ^ d[1] ^ c[29] ^ d[2] ^ c[27] ^ d[4] ^ c[26] ^ d[5] ^ c[25] ^ c[31] ^ d[0] ^ d[6];
            new_crc[14] = c[6] ^ c[31] ^ d[0] ^ c[30] ^ d[1] ^ c[28] ^ d[3] ^ c[27] ^ d[4] ^ c[26] ^ d[5];
            new_crc[15] = c[7] ^ c[31] ^ d[0] ^ c[29] ^ d[2] ^ c[28] ^ d[3] ^ c[27] ^ d[4];
            new_crc[16] = c[8] ^ c[29] ^ d[2] ^ c[28] ^ d[3] ^ c[24] ^ d[7];
            new_crc[17] = c[9] ^ c[30] ^ d[1] ^ c[29] ^ d[2] ^ c[25] ^ d[6];
            new_crc[18] = c[10] ^ c[31] ^ d[0] ^ c[30] ^ d[1] ^ c[26] ^ d[5];
            new_crc[19] = c[11] ^ c[31] ^ d[0] ^ c[27] ^ d[4];
            new_crc[20] = c[12] ^ c[28] ^ d[3];
            new_crc[21] = c[13] ^ c[29] ^ d[2];
            new_crc[22] = c[14] ^ c[24] ^ d[7];
            new_crc[23] = c[15] ^ c[25] ^ d[6] ^ c[24] ^ c[30] ^ d[1] ^ d[7];
            new_crc[24] = c[16] ^ c[26] ^ d[5] ^ c[25] ^ c[31] ^ d[0] ^ d[6];
            new_crc[25] = c[17] ^ c[27] ^ d[4] ^ c[26] ^ d[5];
            new_crc[26] = c[18] ^ c[28] ^ d[3] ^ c[27] ^ d[4] ^ c[24] ^ c[30] ^ d[1] ^ d[7];
            new_crc[27] = c[19] ^ c[29] ^ d[2] ^ c[28] ^ d[3] ^ c[25] ^ c[31] ^ d[0] ^ d[6];
            new_crc[28] = c[20] ^ c[30] ^ d[1] ^ c[29] ^ d[2] ^ c[26] ^ d[5];
            new_crc[29] = c[21] ^ c[31] ^ d[0] ^ c[30] ^ d[1] ^ c[27] ^ d[4];
            new_crc[30] = c[22] ^ c[31] ^ d[0] ^ c[28] ^ d[3];
            new_crc[31] = c[23] ^ c[29] ^ d[2];

            // 合并新 CRC 位
            crc = 0;
            for (int i = 0; i < 32; i++)
            {
                if (new_crc[i])
                    crc |= (1u << i);
            }
        }

        public static uint GetCrcResult()
        {
            return crc;
        }

        public static byte[] GetCrcResultBytes()
        {
            uint inverted = ~crc;
            return BitConverter.GetBytes(inverted); // 小端传输
        }
    }

}
